unit PtContainers;
// This unit is meant to contain a variety of different containers.

interface

uses
  SysUtils, Classes;

type
  EList = class(Exception)
  end;

  //  TUniqueIntegers

  TIntegerObject = record
    int: Integer;
    obj: TObject;
  end;

  TIntegerSet = class
  private
    fArr: array of TIntegerObject;
    fCount: Integer;
    procedure SetCapacity(newCapacity: Integer);
    function GetObjects(i: integer): TObject;
    procedure SetObjects(i: integer; const Value: TObject);
  protected
    procedure SetCount(const Value: Integer);
    procedure Insert(index, int: Integer; obj: TObject);
  public
    function  Add(int: Integer): Integer;
    function  AddObject(int: Integer; obj: TObject): Integer;
    procedure Delete(index: Integer);
    function  Remove(int: Integer): Integer;
    function  IndexOf(int: Integer): Integer;
    property  Objects[i: integer] : TObject read GetObjects write SetObjects;
    procedure Clear;
    property  Count : Integer read fCount;
  end;

implementation

{ TIntegerSet }

function TIntegerSet.Add(int: Integer): Integer;
begin
  Result := AddObject(int, nil);
end;

function TIntegerSet.AddObject(int: Integer; obj: TObject): Integer;
begin
  Result := Count;
  SetCount(Count+1);
  fArr[Result].int := int;
  fArr[Result].obj := obj;
end;

procedure TIntegerSet.Clear;
begin
  fArr := nil;
  fCount := 0;
end;

procedure TIntegerSet.Delete(index: Integer);
var
  i : integer;
begin
  for i := index to Count-2 do
    fArr[i] := fArr[i+1];
  SetCount(Count-1);
end;

function TIntegerSet.GetObjects(i: integer): TObject;
begin
  Result  := fArr[i].obj;
end;

function TIntegerSet.IndexOf(int: Integer): Integer;
begin
  Result := Count-1;
  while Result >= 0 do
    if  fArr[Result].int = int  then
      exit;
end;

procedure TIntegerSet.Insert(index, int: Integer; obj: TObject);
var
  i : integer;
begin
  for i := Count-2 downto index do
    fArr[i+1] := fArr[i];
  fArr[index].int := int;
  fArr[index].obj := obj;
end;

function TIntegerSet.Remove(int: Integer): Integer;
begin
  Result := IndexOf(int);
  if  Result >= 0 then
    Delete(Result);
end;

procedure TIntegerSet.SetCapacity(newCapacity: Integer);
var
  capacity, newSize: Integer;
begin
  capacity := Length(fArr);
  newSize  := capacity;
  if capacity < newCapacity then
    begin
      if newSize = 0  then
        newSize := 8;
      while newSize < newCapacity do
        newSize := newSize shl 1;
    end;
  while newCapacity < newSize shl 1  do
    newSize := newSize shr 1;
  if newSize <> capacity  then
    SetLength(fArr, newSize);
end;

procedure TIntegerSet.SetCount(const Value: Integer);
begin
  SetCapacity(Value);
  fCount := Value;
end;

procedure TIntegerSet.SetObjects(i: integer; const Value: TObject);
begin
  fArr[i].obj := Value;
end;

end.
